package com.jewaton.auth.commons.dao;

import com.jewaton.auth.commons.util.Pager;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.*;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import javax.annotation.Resource;
import java.io.Serializable;
import java.sql.SQLException;
import java.util.*;
import java.util.Map.Entry;


@SuppressWarnings("all")
public abstract class BaseDAO extends HibernateDaoSupport {

	
	
	private static final Log logger = LogFactory.getLog(BaseDAO.class);

	
	// 为父类HibernateDaoSupport注入sessionFactory的值
	@Resource(name = "sessionFactory")
	public void setSuperSessionFactory(SessionFactory sessionFactory) {
		super.setSessionFactory(sessionFactory);
	}
	
	public void evict(Object instance){
		getSession().evict(instance);
		getSession().flush();
	}

	/**
	 * 根据主键id查找对象
	 * @param entityClass
	 * @param id
	 * @return
	 */
	public Object findObjectById(Class entityClass,Serializable id) {
		return getHibernateTemplate().get(entityClass, id);
	}
		
	/**
	 * 保存信息
	 * 
	 * @param entity
	 */
	public void save(Object entity) {
		getHibernateTemplate().save(entity);
	}

	/**
	 * 保存信息，返回序列
	 * 
	 * @param entity
	 */
	public Serializable saves(Object entity) {
		return getHibernateTemplate().save(entity);
	}
	
	/**
	 * 修改信息
	 * 
	 * @param entity
	 */
	public void update(Object entity) {
		getHibernateTemplate().update(entity);
	}
	
	/**
	 * 修改信息
	 * 
	 * @param entity
	 */
	public void saveOrUpdate(Object entity) {
	    getHibernateTemplate().saveOrUpdate(entity);
	}
	
	
	public void merge(Object entity){
		getHibernateTemplate().merge(entity);
	}
	/**
	 * 删除信息
	 * 
	 * @param entity
	 */
	public void delete(Object entity) {
		getHibernateTemplate().delete(entity);
	}
	
	
	public List find(String hql) {
		return getHibernateTemplate().find(hql);
	}
	
	public void flush() {
	    getHibernateTemplate().flush();
	}
	
	/**
	 * 截取第一个匹配记录的结果，没有返回null
	 * @param hql
	 * @return
	 */
	public Object getFirstElement(String hql) {
	    List<Object> list = getHibernateTemplate().find(hql);
	    return list.size() > 0 ? list.get(0) : null;
	}
	/**
	 * 截取第一个匹配记录的结果，没有返回null
	 * @param hql
	 * @return
	 */
	public Object getFirstElement(Query query) {
		query.setMaxResults(1);
	    List<Object> list = query.list();
	    return list.size() > 0 ? list.get(0) : null;
	}
	
	/**
	 * 截取第一个匹配记录的结果，没有返回null
	 * @param hql
	 * @return
	 */
	public Object getFirstElement(String hql,Object... values) {
	    List<Object> list = getHibernateTemplate().find(hql, values);
	    return list.size() > 0 ? list.get(0) : null;
	}
	/**
	 * 获取唯一结果，size不等于1 直接返回null
	 * @param hql
	 * @return
	 */
	public Object uniqueElement(String hql) {
	    List<Object> list = getHibernateTemplate().find(hql);
	    return list.size() == 1 ? list.get(0) : null;
	}
	/**
	 * 获取唯一结果，size不等于1 直接返回null
	 * @param hql
	 * @return
	 */
	public Object uniqueElement(String hql,Object... values) {
	    List<Object> list = getHibernateTemplate().find(hql,values);
	    return list.size() == 1 ? list.get(0) : null;
	}

	
	
	
	

	
	/**
	 * 获取唯一结果，size不等于1 直接返回null
	 * @param hql
	 * @return
	 */
	public Object uniqueElement(Query query) {
		List<Object> list = query.list();
		return list.size() == 1 ? list.get(0) : null;
	}
	
	/**
	 * @param param
	 * @param query
	 */
	protected void setQueryParameters(Map<String, Object> param, Query query) { 
		if(param == null || param.size()==0 || query == null)
			return;
		Iterator<Entry<String, Object>> it = param.entrySet().iterator();
		String hql = query.getQueryString();
		while(it.hasNext()) {
			Entry<String, Object> entry = it.next();
			if(!hql.contains(":"+entry.getKey()))
				continue;
			if(entry.getValue() instanceof Object[]) {
				query.setParameterList(entry.getKey(), (Object[]) entry.getValue());
			}else if(entry.getValue() instanceof Collection) {
				query.setParameterList(entry.getKey(), (Collection) entry.getValue());
			}else
				query.setParameter(entry.getKey(), entry.getValue());
		}
	}
	/**
	 * 过滤器 用于在左右连接时候 在左表或右表添加过滤条件
	 * @see PostMessage 
	 * @see PostMessageDAO
	 * @author czw
	 * @param filterParam key为filter的名字，value为嵌套Map，其中的key为param，value为param参数的值
	 * @param session
	 */
	protected void setFilter(Map<String, Map<String, Object>> filterParam, Session session) {
	    if (filterParam == null || filterParam.size()==0 || session == null)
	        return;
	    Iterator<Entry<String, Map<String, Object>>> it = filterParam.entrySet().iterator();
	    while (it.hasNext()) {
	        Entry<String, Map<String, Object>> entry = it.next();
	        String key = entry.getKey();
	        Filter filter  = session.enableFilter(key);
	        Map<String, Object> map = entry.getValue();
	        Iterator<Entry<String, Object>> iterator = map.entrySet().iterator();
	        while (iterator.hasNext()) {
	            Entry<String, Object> e = iterator.next();
	            filter.setParameter(e.getKey(), e.getValue());
	        }
	    }
	}
	
	protected int countQueryByHql(String hql) {
		return countQueryByHql(hql, null);
	}
	
	/**
	 * edit by czw (统计数量时候去掉排序,去掉select开头的hql语句引起的异常)
	 * edit by chd 添加条件参数
	 * 总记录数
	 * @param hql
	 * @return
	 */
	protected int countQueryByHql(String hql, Map<String, Object> param) {
	    return countQueryByHqlWithFilter(hql, param, null);
	}
	
	protected int countQueryByHqlWithFilter(String hql, Map<String, Object> param, Map<String, Map<String, Object>> filterParam) {
	    int i = -1;
	    if ((i = hql.toUpperCase().indexOf("FROM")) != -1) {
	        hql = hql.substring(i);
	    }
	    i = -1;
	    if ((i = hql.toUpperCase().indexOf("ORDER BY")) != -1) {
	        hql = hql.substring(0, i);
	    }
	    i = -1;
	    hql = hql.replace("fetch", " ");
	    hql = hql.replace("FETCH", " ");
	    String counthql = "SELECT COUNT(*) " + hql;
	    try {
	        Session session = getSession();
	        setFilter(filterParam, session);
	        Query query = session.createQuery(counthql);
	        setQueryParameters(param, query);
	        Object o = null;
	        if ((i = hql.toUpperCase().indexOf("GROUP BY")) != -1){
	        	o = query.list().size();
	        }else {
	        	o= query.uniqueResult();
	        }
	        return Integer.valueOf(o.toString());
	    } catch (Exception e) {
	        throw new RuntimeException("解析hql语句出错: " + e.getMessage()+ "\n\n"  + counthql);
	    }
	}
	

	/**
	 * hql分页实现
	 * @param hql
	 * @param pageNo  不需要分页传-1
	 * @param pageSize 不需要分页传-1	
	 * @return
	 */
	protected List getHQLList(String hql,int start,int end) {
		return getHQLList(hql, null, start, end);
	}
	
	public List getHQLList(String hql, Map<String, Object> param) {
	    return getHQLListWithFilter(hql, param,  null, -1, -1);
	}
	
	public List getHQLList(String hql, Map<String, Object> param, int start,
			int pageSize) {
		return getHQLListWithFilter(hql, param,  null, start, pageSize);
	}
	
	public List getHQLListWithFilter(String hql, Map<String, Object> param, Map<String, Map<String, Object>> filterParam, int start,
	        int pageSize) {
	    Session session = getSession();
	    setFilter(filterParam, session);
	    Query query = session.createQuery(hql);
	    setQueryParameters(param, query);
	    if (start > -1) {                      
	        query.setFirstResult(start);					
	    }
	    if (pageSize > -1) {
	        query.setMaxResults(pageSize);		  	
	    }
	    return query.list();
	}
	
	
	/**
	 * 根据HQL查询分页
	 * @param hql
	 * @param pageNo
	 * @param pageSize
	 * @return
	 */
	protected Pager findPageList(String hql, int pageNo, int pageSize) {
		return findPageList(hql, null, pageNo, pageSize);
	}
	
	/**
	 * 根据HQL查询分页
	 * @param hql
	 * @param pageNo
	 * @param pageSize
	 * @return
	 */
	protected Pager findPageList(String hql, Map<String, Object> param, int pageNo, int pageSize) {
		if (pageNo==-1 && pageSize==-1) {
			return findListWithFilter(hql, param, null, pageNo, pageSize);
		}else{
		}
		return findPageListWithFilter(hql, param, null, pageNo, pageSize);
	}
	
	protected Pager findListWithFilter(String hql, Map<String, Object> param, Map<String, Map<String, Object>> filterParam, int pageNo, int pageSize){
		int totalCount = countQueryByHqlWithFilter(hql, param, filterParam);
		Pager p=new Pager();
		if (totalCount < 1) {
	        p.setList(new ArrayList());
	        return p;
	    }
		List list = getHQLListWithFilter(hql, param, filterParam, p.getStart(), pageSize);
	    p.setList(list);
	    return p;
	}
	
	protected Pager findPageListWithFilter(String hql, Map<String, Object> param, Map<String, Map<String, Object>> filterParam, int pageNo, int pageSize) {
	    int totalCount = countQueryByHqlWithFilter(hql, param, filterParam);
	    Pager p = new Pager(pageNo, pageSize, totalCount);
	    if (totalCount < 1) {
	        p.setList(new ArrayList());
	        return p;
	    }
	    List list = getHQLListWithFilter(hql, param, filterParam, p.getStart(), pageSize);
	    p.setList(list);
	    return p;
	}
	
	
	protected Query createQuery(String hql, Map<String, Object> param) {
	    Query query = getSession().createQuery(hql);
	    setQueryParameters(param, query);
	    return query;
    }
	
	
	
	/**
	 * 查询总条数，支持distinct等子句
	 * @param hql
	 * @param param
	 * @param filterParam
	 * @return
	 */
	protected int countQueryByHqlWithFilterSpecial(String hql, Map<String, Object> param, Map<String, Map<String, Object>> filterParam) {
	    int i = -1;
	    if ((i = hql.toUpperCase().indexOf("FROM")) != -1) {
	        hql = hql.substring(i);
	    }
	    i = -1;
	    if ((i = hql.toUpperCase().indexOf("ORDER BY")) != -1) {
	        hql = hql.substring(0, i);
	    }
	    i = -1;
	    String counthql = "SELECT COUNT(distinct ib.ibaId) " + hql;
	    try {
	        Session session = getSession();
	        setFilter(filterParam, session);
	        Query query = session.createQuery(counthql);
	        setQueryParameters(param, query);
	        Object o = null;
	        o= query.uniqueResult();
	        return Integer.valueOf(o.toString());
	    } catch (Exception e) {
	        throw new RuntimeException("解析hql语句出错: " + e.getMessage()+ "\n\n"  + counthql);
	    }
	}
	
	/**
	 * 查询单页数据，支持group by,distinct等子句
	 * @param hql
	 * @param param
	 * @param filterParam
	 * @param pageNo
	 * @param pageSize
	 * @return
	 */
	protected Pager findListWithFilterSpecial(String hql, Map<String, Object> param, Map<String, Map<String, Object>> filterParam, int pageNo, int pageSize){
		int totalCount = countQueryByHqlWithFilterSpecial(hql, param, filterParam);
		Pager p=new Pager();
		if (totalCount < 1) {
	        p.setList(new ArrayList());
	        return p;
	    }
		List list = getHQLListWithFilter(hql, param, filterParam, p.getStart(), pageSize);
	    p.setList(list);
	    return p;
	}
	
	/**
	 * 根据HQL查询分页，支持group by, distinct 等查询 - 高志林
	 * @param hql
	 * @param pageNo
	 * @param pageSize
	 * @return
	 */
	protected Pager findPageListWithFilterSpecial(String hql, Map<String, Object> param, Map<String, Map<String, Object>> filterParam, int pageNo, int pageSize) {
		int totalCount = countQueryByHqlWithFilterSpecial(hql, param, filterParam);
	    Pager p = new Pager(pageNo, pageSize, totalCount);
	    if (totalCount < 1) {
	        p.setList(new ArrayList());
	        return p;
	    }
	    List list = getHQLListWithFilter(hql, param, filterParam, p.getStart(), pageSize);
	    p.setList(list);
	    return p;
	}
	
	/**
	 * 根据HQL查询分页，支持group by, distinct 等查询 - 高志林
	 * @param hql
	 * @param pageNo
	 * @param pageSize
	 * @return
	 */
	protected Pager findPageListSpecial(String hql, Map<String, Object> param, int pageNo, int pageSize) {
		if (pageNo==-1 && pageSize==-1) {
			return findListWithFilterSpecial(hql, param, null, pageNo, pageSize);
		}else{
		}
		return findPageListWithFilterSpecial(hql, param, null, pageNo, pageSize);
	}
	
	//************************* sql******************************************************************************//
	
	protected Query createSQLQuery(String sql, Map<String, Object> param) {
	    Query query = getSession().createSQLQuery(sql); 
	    setQueryParameters(param, query);
	    return query;
	}
	
	public List getSQLListWithFilter(String hql, Map<String, Object> param, Map<String, Map<String, Object>> filterParam, int start,
	        int pageSize) {
	    Session session = getSession();
//	    setFilter(filterParam, session);
	    Query query = session.createSQLQuery(hql);
	    setQueryParameters(param, query);
	    if (start > -1) {                      
	        query.setFirstResult(start);					
	    }
	    if (pageSize > -1) {
	        query.setMaxResults(pageSize);		  	
	    }
	    return query.list();
	}
	
	/**
	 * 总记录数
	 * @param sql
	 * @return
	 */
	protected int countQueryBySql(String sql){
	    return countQueryBySql(sql, null);
	}
	/**
	 * 总记录数
	 * @param sql
	 * @return
	 */
	protected int countQueryBySql(String sql,Map<String, Object> param){ 
	    int i = -1;
	    if ((i = sql.toLowerCase().indexOf("order by")) != -1) {
	        sql = sql.substring(0, i);
	    }
	    String countSql = "SELECT COUNT(*) FROM ( " + sql + ")";
	    try {
	        Query query = getSession().createSQLQuery(countSql);
	        setQueryParameters(param, query);
	        Object o= query.uniqueResult();
	        return Integer.valueOf(o.toString());
	    } catch (Exception e) {
            throw new RuntimeException("解析hql语句出错: " + e  + countSql);
	    }
	}
	

	
	/**
	 * sql分页实现
	 * @param sql
	 * @param pageNo  不需要分页传-1
	 * @param pageSize 不需要分页传-1	
	 * @return
	 */
	protected List getSQLList(final String sql,final int start,final int end) {
		return getSQLList(sql, null, start, end);
	}
	
	/**
	 * sql分页实现
	 * @param sql
	 * @param pageNo  不需要分页传-1
	 * @param pageSize 不需要分页传-1	
	 * @return
	 */
	protected List getSQLList(final String sql, final Map<String, Object> param, final int start, final int end) {
	    return this.getHibernateTemplate().executeFind(new HibernateCallback(){ 
	        public Object doInHibernate(Session session)throws HibernateException, SQLException {
	        	Query query = session.createSQLQuery(sql);
	            setQueryParameters(param, query);
	            if (start > -1) {                      
	                query.setFirstResult(start);					
	            }
	            if (end > -1) {
	                query.setMaxResults(end);		  	
	            }
	            return query.list();
	        }
	    });
	}
	
	/**
	 * sql分页实现
	 * @param sql
	 * @param pageNo  不需要分页传-1
	 * @param pageSize 不需要分页传-1	
	 * @return
	 */
	protected List getSQLList(final String sql, final Map<String, Object> param, final int start, final int end,final Class entityClass) {
	    return this.getHibernateTemplate().executeFind(new HibernateCallback(){ 
	        public Object doInHibernate(Session session)throws HibernateException, SQLException {
	        	SQLQuery query = session.createSQLQuery(sql);
	            setQueryParameters(param, query);
	           
	            if(entityClass != null)
	            	query.addEntity(entityClass);
	            	 //query.setResultTransformer(Transformers.aliasToBean(entityClass));
	            if (start > -1) {                      
	                query.setFirstResult(start);					
	            }
	            if (end > -1) {
	                query.setMaxResults(end);		  	
	            }
	            
	            return query.list();
	        }
	    });
	}
	
	/**
	 * 根据SQL查询分页
	 * @param sql
	 * @param pageNo
	 * @param pageSize
	 * @return
	 */
	protected Pager findPageListBySql(String sql, int pageNo, int pageSize) {
	    return findPageListBySql(sql, null, pageNo, pageSize);
	}
	/**
	 * 根据SQL查询分页
	 * @param sql
	 * @param pageNo
	 * @param pageSize
	 * @return
	 */
	protected Pager findPageListBySql(String sql, int pageNo, int pageSize,Class entityClass) {
	    return findPageListBySql(sql, null, pageNo, pageSize,entityClass);
	}
	
	/**
	 * 根据SQL查询分页
	 * @param sql
	 * @param pageNo
	 * @param pageSize
	 * @return
	 */
	protected Pager findPageListBySql(String sql, Map<String, Object> param, int pageNo, int pageSize) {
	    int totalCount = countQueryBySql(sql, param);
	    Pager p = new Pager(pageNo, pageSize, totalCount);
	    if (totalCount < 1) {
	        p.setList(new ArrayList());
	        return p;
	    }
	    List list = getSQLList(sql, param, p.getStart(), pageSize);
	    p.setList(list);
	    return p;
	}
	/**
	 * 根据SQL查询分页
	 * @param sql
	 * @param pageNo
	 * @param pageSize
	 * @return
	 */
	protected Pager findPageListBySql(String sql, Map<String, Object> param, int pageNo, int pageSize,Class entityClass) {
	    int totalCount = countQueryBySql(sql, param);
	    Pager p = new Pager(pageNo, pageSize, totalCount);
	    if (totalCount < 1) {
	        p.setList(new ArrayList());
	        return p;
	    }
	    List list = getSQLList(sql, param, p.getStart(), pageSize,entityClass);
	    p.setList(list);
	    return p;
	}
	
	
	
}
